package com.mes.task.dao;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

import javax.annotation.Resource;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.Criteria;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.MatchMode;
import org.hibernate.criterion.Property;
import org.hibernate.criterion.Restrictions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessResourceFailureException;
import org.springframework.stereotype.Repository;

import com.bstek.dorado.data.provider.Page;
import com.bstek.dorado.util.TempFileUtils;
import com.mes.common.dao.BasicDao;
import com.mes.common.util.SysUtil;
import com.mes.schedule.domain.DemandSTaskLink;
import com.mes.schedule.domain.SPartTask;
import com.mes.task.dao.iface.IDemandDao;
import com.mes.task.dao.iface.IDemandLinkDao;
import com.mes.task.domain.Demand;
import com.mes.task.domain.DemandLink;

@Repository
public class DemandDao extends BasicDao<Demand> implements IDemandDao {
	
	@Resource
	SysUtil sysUtil;

	private static final Log log = LogFactory.getLog(DemandDao.class);

	@Autowired
	IDemandLinkDao demandLinkDao;
	
	/**
	 * 获取架次计划界面上的Demand
	 * @author cswen
	 * @param partUid
	 * @param model
	 * @param drawingId
	 * @param batchNum
	 * @param page
	 * @return List<Demand>
	 * @throws Exception
	 */
	public List<Demand> getAssembleAODemand(String partUid, String model,
			String drawingId, String batchNum, Page page) throws Exception {
		List<Demand> demandList = null;
		try {
			DetachedCriteria crit = DetachedCriteria.forClass(Demand.class);
			crit.createAlias("part", "p");
			if (StringUtils.isNotBlank(partUid)) {
				crit.add(Restrictions.eq("partUid", partUid));
			}
			if (StringUtils.isNotBlank(model)) {
				crit.add(Restrictions.like("model", model, MatchMode.ANYWHERE));
			}
			if (StringUtils.isNotBlank(drawingId)) {
				crit.add(Restrictions.like("p.drawingId", drawingId, MatchMode.ANYWHERE));
			}
			if (StringUtils.isNotBlank(batchNum)) {
				crit.add(Restrictions.like("batchNum", batchNum, MatchMode.ANYWHERE));
			}
			crit.add(Restrictions.eq("demandType",
					Demand.DEMANDTYPE_AO_ASSEMBLY_MPS));
			crit.add(Restrictions.like("masterShopUid", sysUtil
					.getSessionDeptUid(), MatchMode.START));
			crit.addOrder(Property.forName("createTime").desc());
			crit.addOrder(Property.forName("lateFinish").asc());
			crit.addOrder(Property.forName("p.drawingId").asc());
			if (page != null) {
				this.pagingQuery(page, crit);
			} else {
				demandList = this.query(crit, null);
			}
			demandList = this.query(crit, null);
		} catch (DataAccessResourceFailureException e) {
			e.printStackTrace();
		} catch (HibernateException e) {
			e.printStackTrace();
		} catch (IllegalStateException e) {
			e.printStackTrace();
		}
		return demandList;
	}

	/**
	 * @author snowbear
	 * @time 2017/7/18
	 * 通过图号和架次号查询demand
	 * 暂时没有考虑分页查询,暂时屏蔽掉demandType，demandState相关属性查询，不知道有什么问题
	 */
	@Override
	public List<Demand> getProductDemands(String drawingId, String contignationNumber, Page<Demand> page) {
		List<Demand> list = new ArrayList<>();
		try {
			//DetachedCriteria crit = DetachedCriteria.forClass(Demand.class);
			Session session = this.getSessionFactory().getCurrentSession();
			Criteria crit = session.createCriteria(Demand.class);
			//crit.createAlias("part", "p");
			if(drawingId.equals("%")&&!contignationNumber.equals("%")) {
				String temp = "%" + contignationNumber +"%"; 
				crit.add(Restrictions.like("batchNum", temp));
			}else if(!drawingId.equals("%")&&contignationNumber.equals("%")) {
				String temp = "%" + drawingId +"%"; 
				crit.add(Restrictions.like("partDrawingId", temp));
			}else if(!drawingId.equals("%")&&!contignationNumber.equals("%")) {
				String tempDrawingId = "%" + drawingId +"%"; 
				String tempConfig = "%" + contignationNumber +"%"; 
				crit.add(Restrictions.like("partDrawingId", tempDrawingId));
				crit.add(Restrictions.like("batchNum", tempConfig));
			}
			/*crit.add(Restrictions.eq("demandType", Demand.DEMANDTYPE_ORDER));
			crit.add(Restrictions.lt("demandState", Demand.DEMANDSTATE_FINISHED));*/
			//crit.addOrder(Property.forName("lateFinish").asc());
			/*if (page != null) {
				this.pagingQuery(page, crit);
			} else {
				list = this.query(crit, null);
			}*/
			/*List list2 = new ArrayList<>();
			list2 = crit.list();*/
			list = crit.list();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return list;

	}

	public List<Demand> getStartedDemandsForTasks(String partUid, String masterShopUid, Page<Demand> page) {
		List<Demand> list = null;
		try {
			DetachedCriteria crit = DetachedCriteria.forClass(Demand.class);

			crit.add(Restrictions.eq("partUid", partUid));
			crit.add(Restrictions.like("demandState", Demand.DEMANDSTATE_STARTED));
			crit.add(Restrictions.like("masterShopUid", masterShopUid));
			crit.addOrder(Property.forName("lateFinish").asc());

			// 如果需要进行分页处理，则调用如下语句
			if (page != null) {
				this.pagingQuery(page, crit);
			} else {
				list = this.query(crit, null);
			}
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return list;
	}

	/**
	 * 获取物料的当月计划
	 * 
	 * @param partUid
	 *            物料图号
	 * @return 返回当月计划集合
	 */
	@Override
	public List<Demand> getPartOrder(String partUid) {
		List<Demand> list = null;
		try {
			Session session = this.getSession();
			Criteria crit = session.createCriteria(Demand.class);
			crit.add(Restrictions.eq("partUid", partUid));
			crit.add(Restrictions.eq("demandType", Demand.DEMANDTYPE_MISSING_PART));
			crit.add(Restrictions.lt("demandState", Demand.DEMANDSTATE_FINISHED));

			Calendar calFrom = Calendar.getInstance();
			calFrom.set(Calendar.DATE, calFrom.getActualMinimum(Calendar.DATE));

			Calendar calTo = Calendar.getInstance();
			calTo.set(Calendar.DATE, calTo.getActualMaximum(Calendar.DATE));

			crit.add(Restrictions.between("lateFinish", calFrom.getTime(), calTo.getTime()));
			list = crit.list();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return list;
	}


	@Override
	public List<Demand> getProductDemandByDate(String drawingId, String demandId, Date startDate, Date endDate,
			Page page) {
		List<Demand> list = null;
		try {
			DetachedCriteria crit = DetachedCriteria.forClass(Demand.class);
			crit.createAlias("part", "p");
			crit.add(Restrictions.like("p.drawingId", drawingId));
			crit.add(Restrictions.like("demandId", demandId));
			if (startDate != null && endDate != null) {
				crit.add(Restrictions.between("earlyStart", startDate, endDate));
			}
			crit.add(Restrictions.eq("demandType", Demand.DEMANDTYPE_ORDER));
			crit.add(Restrictions.le("demandState", Demand.DEMANDSTATE_FINISHED));
			crit.addOrder(Property.forName("p.drawingId").asc());
			crit.addOrder(Property.forName("lateFinish").asc());
			crit.addOrder(Property.forName("earlyStart").asc());
			if (page != null) {
				this.pagingQuery(page, crit);

			} else {
				list = this.query(crit, null);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return list;

	}

	@Override
	public List<Demand> getPredDemandsByDept(String succDemandUid, String masterShopUid, Page page) {
		List<Demand> list = new ArrayList<Demand>();
		
		List<DemandLink> demandLinklist = null;
		try {
			DetachedCriteria crit = DetachedCriteria.forClass(DemandLink.class);
			crit.createAlias("predDemand", "p");
			crit.createAlias("p.part", "pp");
			crit.add(Restrictions.like("p.masterShopUid", masterShopUid + "%"));
			crit.add(Restrictions.eq("succDemandUid", succDemandUid));
			crit.add(Restrictions.lt("p.demandState", Demand.DEMANDSTATE_FINISHED));
			crit.addOrder(Property.forName("p.demandState").asc());
			crit.addOrder(Property.forName("pp.drawingId").asc());
			if (page != null) {
				Page<DemandLink> page1 = new Page<DemandLink>(page.getPageSize(), page.getPageNo());
				demandLinkDao.pagingQuery(page1, crit);
				demandLinklist = new ArrayList<DemandLink>();
				demandLinklist.addAll(page1.getEntities());
				page.setEntityCount(page1.getEntityCount());
			} else {
				demandLinklist = demandLinkDao.query(crit, null);
			}
			
			if (demandLinklist != null && demandLinklist.size() != 0) {
				for (DemandLink demandLink : demandLinklist) {
					list.add(demandLink.getPredDemand());
				}
			}
			
			if (page != null) 
				page.setEntities(list);
			

		} catch (Exception e) {
			e.printStackTrace();
		}
		return list;

	}

	@Override
	public List<Demand> getReceivedDemands(String masterShopUid, String partUid) {
		List<Demand> list = null;
		try {
			Session session = this.getSession();
			Criteria crit = session.createCriteria(Demand.class);

			crit.add(Restrictions.eq("demandState", Demand.DEMANDSTATE_STARTED));
			crit.add(Restrictions.like("masterShopUid", masterShopUid));
			crit.add(Restrictions.like("partUid", partUid));

			crit.addOrder(Property.forName("lateFinish").asc());

			list = crit.list();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return list;
	}

	@Override
	public List<Demand> getReceivedDemandsByPartuid(String partUid) {
		List<Demand> list = null;
		try {
			Session session = this.getSession();
			Criteria crit = session.createCriteria(Demand.class);

			crit.add(Restrictions.eq("demandState", Demand.DEMANDSTATE_STARTED));
			crit.add(Restrictions.like("partUid", partUid));

			crit.addOrder(Property.forName("lateFinish").asc());

			list = crit.list();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} 
		return list;
	}

	@Override
	public List<Demand> getPredDemands(String succDemandUid, Page<Demand> page) {
		List<Demand> list = new ArrayList<Demand>();
		List<DemandLink> demandLinklist = null;
		try {
			DetachedCriteria crit = DetachedCriteria.forClass(DemandLink.class);
			crit.createAlias("predDemand", "p");
			crit.createAlias("p.part", "pp");
			crit.add(Restrictions.eq("succDemandUid", succDemandUid));
			crit.addOrder(Property.forName("pp.partType").asc());
			crit.addOrder(Property.forName("pp.drawingId").asc());
			if (page != null) {
				Page<DemandLink> page1 = new Page<DemandLink>(page.getPageSize(), page.getPageNo());
				demandLinkDao.pagingQuery(page1, crit);
				page.setEntityCount(page1.getEntityCount());
			} else {
				demandLinklist = demandLinkDao.query(crit, null);
			}
			if (demandLinklist != null && demandLinklist.size() != 0) {
				for (DemandLink demandLink : demandLinklist) {
					Demand demand = this.getById(demandLink.getPredDemandUid());
					list.add(demand);
				}
			}
			if (page != null) {
				page.setEntities(list);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return list;
	}

//	@Override
//	public List<Demand> getWarningDemand(Page<Demand> page) {
//		List<Demand> demandList = null;
//		try {
//			Session session = this.getSession();
//			Criteria crit = session.createCriteria(Demand.class);
//			crit.createAlias("part", "p");
//			crit.add(Restrictions.like("masterShopUid", MMUtils.getSessionDeptId() + "%"));
//			crit.add(Restrictions.eq("demandType", Demand.DEMANDTYPE_ORDER));
//			// crit.add(Restrictions.or(Restrictions.isNull("materialState"),Restrictions.eq("materialState",
//			// Demand.DEMANDMATERIALSTATE_NOTREADY)));
//			crit.add(Restrictions.eq("materialState", Demand.DEMANDMATERIALSTATE_NOTREADY));
//			crit.add(Restrictions.and(Restrictions.isNotNull("readyPoint"), Restrictions.gt("readyPoint", 0)));
//			crit.add(Restrictions.lt("demandState", Demand.DEMANDSTATE_FINISHED));
//			crit.add(Restrictions.or(
//					Restrictions.or(Restrictions.isNull("planFinish"), Restrictions.isNull("lateFinish")),
//					Restrictions.gtProperty("planFinish", "lateFinish")));
//			crit.addOrder(Property.forName("lateFinish").asc());
//			crit.addOrder(Property.forName("p.drawingId").asc());
//			if (page != null)
//				page.pagePro(crit);
//			demandList = crit.list();
//
//		} catch (Exception e) {
//			e.printStackTrace();
//		}
//		return demandList;
//	}
//
//	@Override
//	public List<Demand> getReadyNoticeDemand(String demandUid, String partUid, Page page) {
//		List<Demand> demandList = null;
//		try {
//			Session session = this.getSession();
//			Criteria crit = session.createCriteria(Demand.class);
//			crit.createAlias("part", "p");
//			if (demandUid != null && !("".equals(demandUid))) {
//				crit.add(Restrictions.eq("demandUid", demandUid));
//			}
//			if (partUid != null && !("".equals(partUid))) {
//				crit.add(Restrictions.eq("partUid", partUid));
//			}
//			crit.add(Restrictions.like("masterShopUid", MMUtils.getSessionDeptId() + "%"));
//			crit.add(Restrictions.and(Restrictions.isNotNull("readyPoint"), Restrictions.gt("readyPoint", 0)));
//			crit.add(Restrictions.eq("materialState", Demand.DEMANDMATERIALSTATE_READY));
//			// crit.add(Restrictions.eq("demandType", Demand.DEMANDTYPE_ORDER));
//			crit.add(Restrictions.lt("demandState", Demand.DEMANDSTATE_FINISHED));
//			crit.add(Restrictions.gtProperty("dueQty", "arrangeQty"));
//			crit.addOrder(Property.forName("lateFinish").asc());
//			crit.addOrder(Property.forName("p.drawingId").asc());
//			if (page != null)
//				page.pagePro(crit);
//			demandList = crit.list();
//
//		} catch (Exception e) {
//			e.printStackTrace();
//		}
//		return demandList;
//	}
//
//	@Override
//	public List<Demand> getModelDemands(String model, String masterShopUid, Page page) {
//		List<Demand> list = null;
//		try {
//			Session session = this.getSession();
//			Criteria crit = session.createCriteria(Demand.class);
//			crit.add(Restrictions.like("masterShopUid", masterShopUid));
//			crit.add(Restrictions.eq("model", model));
//			crit.add(Restrictions.le("demandState", Demand.DEMANDSTATE_STARTED));
//			crit.createAlias("part", "p");
//			// crit.add(Restrictions.or(Restrictions.eq("p.className", "产品"),
//			// Restrictions.eq("p.className", "组件")));
//			// 如果需要进行分页处理，则调用如下语句
//			if (page != null)
//				page.pagePro(crit);
//
//			crit.addOrder(Property.forName("p.drawingId").asc());
//			list = crit.list();
//		} catch (Exception e) {
//			e.printStackTrace();
//		}
//		return list;
//	}
//
//	@Override
//	public List<Demand> getDemandsByPartUid(String partUid, Page page) {
//		List<Demand> list = null;
//		try {
//			Session session = this.getSession();
//			Criteria crit = session.createCriteria(Demand.class);
//			crit.add(Restrictions.eq("partUid", partUid));
//			crit.add(Restrictions.like("masterShopUid", MMUtils.getSessionDeptId(), MatchMode.START));
//			crit.add(Restrictions.lt("demandState", Demand.DEMANDSTATE_FINISHED));
//			if (page != null)
//				page.pagePro(crit);
//
//			crit.addOrder(Property.forName("createTime").desc());
//			list = crit.list();
//		} catch (Exception e) {
//			e.printStackTrace();
//		}
//		return list;
//	}
//
//	@Override
//	public List<Demand> getAssembleAODemand(String partUid, String batchNum, Page page) {
//
//		List<Demand> demandList = null;
//		try {
//			Session session = this.getSession();
//			Criteria crit = session.createCriteria(Demand.class);
//			crit.createAlias("part", "p");
//			if (StringUtils.isNotBlank(partUid)) {
//				crit.add(Restrictions.eq("partUid", partUid));
//			}
//			if (StringUtils.isNotBlank(batchNum)) {
//				crit.add(Restrictions.eq("demandId", batchNum));
//			}
//			crit.add(Restrictions.eq("demandType", Demand.DEMANDTYPE_AO_ASSEMBLY_MPS));
//			crit.add(Restrictions.like("masterShopUid", MMUtils.getSessionDeptId(), MatchMode.START));
//			crit.addOrder(Property.forName("createTime").desc());
//			crit.addOrder(Property.forName("lateFinish").asc());
//			crit.addOrder(Property.forName("p.drawingId").asc());
//			if (page != null) {
//				page.pagePro(crit);
//			}
//			demandList = crit.list();
//
//		} catch (Exception e) {
//			e.printStackTrace();
//		}
//		return demandList;
//	}

	/**
	 * modify from dbhandler to session&criteria
	 * 
	 * @see use for DemandSTaskLinkManager
	 * @param demandUid
	 * @param scheduleUid
	 * @return
	 */
	public double getArrangeQty(String demandUid, String scheduleUid) {

		double a = 0;
		try {
			String sqlArrangeQty = " select nvl(sum(tl.linkqty), 0) as linkQty" + " from T_SCHEDULE_DEMANDTASKLINK tl "
					+ " where tl.demandUid = ? " + " and tl.scheduleuid = ?  and tl.isIneffect=1";
			Session session = this.getSession();
			Criteria crit = session.createCriteria(DemandSTaskLink.class);
			crit.add(Restrictions.eq("demandUid", demandUid));
			crit.add(Restrictions.eq("scheduleUid", scheduleUid));
			crit.add(Restrictions.eq("isInEffect", 1));
			List<DemandSTaskLink> list = new ArrayList<>();
			list = crit.list();
			for (int i = list.size() - 1; i >= 0; i--) {
				DemandSTaskLink tempObject = list.get(i);
				a += tempObject.getLinkQty() == null ? 0 : tempObject.getLinkQty();
			}
		} catch (Exception e) {
			e.printStackTrace();

		}
		return a;
	}

	/**
	 * @see use for DemandSTaskLinkManager
	 * @param demandUid
	 * @param scheduleUid
	 * @return
	 */
	public Date getPlanFinish(String demandUid, String scheduleUid) {

		Date a = null;
		try {
			Session session = this.getSession();
			Criteria crit = session.createCriteria(DemandSTaskLink.class, "dst");
			crit.add(Restrictions.eq("demandUid", demandUid));
			crit.add(Restrictions.eq("scheduleUid", scheduleUid));
			crit.add(Restrictions.eq("isInEffect", 1));
			// create connection to another table select mode inner join
			crit.createAlias("partTask", "sp", Criteria.INNER_JOIN);
			crit.add(Restrictions.eqProperty("dst.partTaskUid", "sp.taskUid"));
			crit.add(Restrictions.eqProperty("dst.scheduleUid", "sp.scheduleUid"));
			crit.add(Restrictions.lt("sp.taskState", 106));
			List<SPartTask> tempList = crit.list();
			if (tempList.isEmpty())
				return null;
			// property coordinate?
			a = tempList.get(0).getPlanFinish();
			for (int i = tempList.size() - 1; i >= 0; i--) {
				if (a.before(tempList.get(i).getPlanFinish())) {
					a = tempList.get(i).getPlanFinish();
				}
			}
			/**
			 * new knowledge criteria innner join
			 */

			String sqlPlanFinish = " select max(t.planFinish) as planFinish " + " from T_SCHEDULE_DEMANDTASKLINK tl"
					+ " inner join t_schedule_parttask t " + "  on tl.taskuid = t.taskuid "
					+ "  and tl.scheduleuid=t.scheduleuid " + "  where tl.demanduid = ?" + "  and tl.scheduleuid = ?"
					+ "  and tl.isIneffect = 1" + "  and t.taskstate < 106";

		} catch (Exception e) {
			e.printStackTrace();

		} finally {
		}

		return a;
	}

	/**
	 * @see use for DemandSTaskLinkManager
	 * @param demandUid
	 * @param scheduleUid
	 * @return
	 */
	public double getRemainQty(String demandUid, String scheduleUid) {

		double a = 0;
		try {
			Session session = this.getSession();
			Criteria crit = session.createCriteria(DemandSTaskLink.class, "t1");
			crit.add(Restrictions.eq("t1.demandUid", demandUid));
			crit.add(Restrictions.eq("t1.scheduleUid", scheduleUid));
			crit.add(Restrictions.eq("t1.isInEffect", 1));
			List<DemandSTaskLink> linkqtyList = crit.list();
			double sum = 0.0;
			for (int i = linkqtyList.size() - 1; i >= 0; i--) {
				if (linkqtyList.get(i).getLinkQty() == null)
					continue;
				sum += linkqtyList.get(i).getLinkQty();
			}
			Criteria crita = session.createCriteria(Demand.class);
			crita.add(Restrictions.eq("demandUid", demandUid));
			Demand demand = (Demand) crita.uniqueResult();
			double dueQty = 0.0;
			double deliveryQty = 0.0;
			if (demand.getDueQty() != null)
				dueQty = demand.getDueQty();
			if (demand.getDeliveryQty() != null)
				deliveryQty = demand.getDeliveryQty();
			a = dueQty - deliveryQty - sum;

			String sqlRemainQty = " select (t.dueQty -t.DELIVERYQTY- (select nvl(sum(tl.linkqty), 0)"
					+ " from T_SCHEDULE_DEMANDTASKLINK tl" + " where tl.demandUid = ?"
					+ " and tl.scheduleuid = ? and tl.ISINEFFECT = 1)) as remainQty" + " from t_demand t"
					+ " where t.demanduid = ?";

		} catch (Exception e) {
			e.printStackTrace();
		} finally {
		}
		return a;
	}

	@Override
	public List<Demand> getReceivedDemands(String masterShopUid, Page<Demand> page) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public List<Demand> getReceivedDemands(Page<Demand> page) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public List<Demand> getUnArrangeDemands(String masterShopUid, Page<Demand> page) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public List<Demand> getUnArrangeDemands(String masterShopUid, String partUid, Page<Demand> page) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public List<Demand> getWarningDemand(Page<Demand> page) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public List<Demand> getReadyNoticeDemand(String demandUid, String partUid, Page<Demand> page) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public List<Demand> getUnFinishProductDemandByPartUid(String partUid, Page<Demand> page) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public List<Demand> getModelDemands(String model, String masterShopUid, Page<Demand> page) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public List<Demand> getDemandsByPartUid(String partUid, Page<Demand> page) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public List<Demand> getAssembleAODemand(String partUid, String batchNum, Page<Demand> page) {
		// TODO Auto-generated method stub
		return null;
	}

}
